package proyecto.testcasetool.presentation.details.usecase;

import org.eclipse.core.databinding.ObservablesManager;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.databinding.EMFDataBindingContext;
import org.eclipse.emf.databinding.edit.EMFEditObservables;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.edit.provider.AdapterFactoryItemDelegator;
import org.eclipse.emf.edit.provider.IItemPropertyDescriptor;
import org.eclipse.emf.edit.provider.ItemProvider;
import org.eclipse.emf.edit.ui.celleditor.FeatureEditorDialog;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryContentProvider;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider;
import org.eclipse.emf.edit.ui.provider.ExtendedImageRegistry;
import org.eclipse.jface.databinding.swt.SWTObservables;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.ListViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.forms.IFormPart;
import org.eclipse.ui.forms.widgets.ExpandableComposite;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;

import proyecto.testcasetool.Actor;
import proyecto.testcasetool.TestcasetoolPackage;
import proyecto.testcasetool.UseCase;
import proyecto.testcasetool.UseCaseModel;
import proyecto.testcasetool.presentation.details.DetailsPage;
import proyecto.testcasetool.presentation.editor.TestcasetoolEditorPlugin;
import proyecto.testcasetool.presentation.editor.pages.FormLayoutFactory;
import proyecto.testcasetool.provider.TestcasetoolEditPlugin;



public class UseCaseDetailsPage extends DetailsPage {
	private Text txtUsecasename;
	private Text txtDescription;
	private Text txtPreConditions;
	private Text txtPostConditions;
	
	private AdapterFactoryItemDelegator afid;
	private ListViewer listViewer;

	
	private ObservablesManager obsManager;
	private EMFDataBindingContext bindingContext;
	
	public UseCaseDetailsPage(FormToolkit toolkit, EditingDomain editingDomain,
			AdapterFactory adapterFactory) {
		super(toolkit, editingDomain, adapterFactory);
		afid =  new AdapterFactoryItemDelegator(adapterFactory);
		
		bindingContext = new EMFDataBindingContext();
		obsManager = new ObservablesManager();
	}

	@Override
	protected void createDetailsSection(final Composite parent) {
		GridLayout gridLayout = (GridLayout) parent.getLayout();
		gridLayout.verticalSpacing = 5;

		Section s = toolkit.createSection(parent, Section.TITLE_BAR);
		s.setText("Use case details");
		s.setLayoutData(new GridData(GridData.FILL_BOTH));
		s.setLayout(FormLayoutFactory.createDetailsGridLayout(false, 1));
		
		Composite client = toolkit.createComposite(s,SWT.FILL);
		
		s.setClient(client);
		client.setLayout(new GridLayout(2, false));
		toolkit.paintBordersFor(client);
		
		Label lblName = toolkit.createLabel(client, "Name", SWT.NONE);
		GridData gd_lblName = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1);
		gd_lblName.verticalIndent = 2;
		lblName.setLayoutData(gd_lblName);
		
		txtUsecasename = toolkit.createText(client, "New Text", SWT.NONE);
	
		GridData gd_txtUsecasename = new GridData(SWT.LEFT, SWT.CENTER, true, false, 1, 1);
		gd_txtUsecasename.verticalIndent = 2;
		gd_txtUsecasename.widthHint = 244;
		txtUsecasename.setLayoutData(gd_txtUsecasename);
		
		Label lblDescription = toolkit.createLabel(client, "Description", SWT.NONE);
		txtDescription = toolkit.createText(client, "", SWT.WRAP | SWT.V_SCROLL | SWT.MULTI);
		
		GridData gd_txtDescription = new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1);
		gd_txtDescription.heightHint = 80;
		gd_txtDescription.verticalIndent = 10;
		gd_txtDescription.widthHint = 0;
		txtDescription.setLayoutData(gd_txtDescription);
		
		Label lblPrecondition = toolkit.createLabel(client, "Pre-conditions", SWT.NONE);
		txtPreConditions = toolkit.createText(client, "", SWT.WRAP | SWT.V_SCROLL | SWT.MULTI);
		
		
		GridData gd_txtPreConditions = new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1);
		gd_txtPreConditions.heightHint = 80;
		gd_txtPreConditions.verticalIndent = 10;
		gd_txtPreConditions.widthHint = 0;
		txtPreConditions.setLayoutData(gd_txtPreConditions);
		
		Label lblPostcondition = toolkit.createLabel(client, "Post-conditions", SWT.NONE);
		
		txtPostConditions = toolkit.createText(client, "", SWT.WRAP | SWT.V_SCROLL | SWT.MULTI);
		
		
		GridData gd_txtPostConditions = new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1);
		gd_txtPostConditions.heightHint = 80;
		gd_txtPostConditions.verticalIndent = 10;
		gd_txtPostConditions.widthHint = 380;
		txtPostConditions.setLayoutData(gd_txtPostConditions);
		toolkit.paintBordersFor(client);
		
		Composite sectionsActorsAndIncludedCases = toolkit.createComposite(parent,SWT.FILL);
		sectionsActorsAndIncludedCases.setLayout(new GridLayout(2, true));
		sectionsActorsAndIncludedCases.setLayoutData(new GridData(GridData.FILL_BOTH));
		
		createActorsSection(sectionsActorsAndIncludedCases);
		
		
	}
	
	public void selectionChanged(IFormPart part, ISelection selection) {
		// controlar que sea la part que esto esperando!!!!
		if (!(selection instanceof IStructuredSelection)) {
			return;
		}
		EObject newEObject = getEObjectFromSelection(selection);
		if (newEObject != null && newEObject != eObject) {
			eObject = newEObject;
			if (eObject != null) {
				System.out.println("UseCaseDetailsPage.selectionChanged"+
						"\n"+part+"\n"+selection);
				
				refreshActors();
				
				IObservableValue obsDescFeature = EMFEditObservables
						.observeValue(editingDomain, eObject,
								TestcasetoolPackage.Literals.USE_CASE__DESCRIPTION);

				
				bindingContext.bindValue(SWTObservables.observeText(
						txtDescription, SWT.FocusOut), obsDescFeature);

				
				IObservableValue obsNameFeature = EMFEditObservables
						.observeValue(editingDomain, eObject,
								TestcasetoolPackage.Literals.USE_CASE__NAME);

				bindingContext.bindValue(
						SWTObservables.observeDelayedValue(400, SWTObservables
								.observeText(txtUsecasename, SWT.Modify)),
						obsNameFeature);
				
				
//				IEMFEditValueProperty preCondProp = EMFEditProperties.value(
//						  editingDomain,
//						  FeaturePath.fromList(
//								  TestcasetoolPackage.Literals.USE_CASE__PRE_CONDITION,
//						    TestcasetoolPackage.Literals.CONDITION__EXPRESSION
//						  )
//						);
//				
//				IObservableValue obsPreCondition = preCondProp.observe(eObject);
				
				IObservableValue obsPreCondition = EMFEditObservables
						.observeValue(editingDomain, eObject,
								TestcasetoolPackage.Literals.USE_CASE__PRE_CONDITION);

				bindingContext.bindValue(SWTObservables.observeText(txtPreConditions, SWT.FocusOut), obsPreCondition);
					
				
				// lo de abajo es cuando puede ser null el objeto que es attributo
				
//				IEMFEditValueProperty preCondProp = EMFEditProperties.value(
//						  editingDomain,
//						  FeaturePath.fromList(
//								  TestcasetoolPackage.Literals.USE_CASE__PRE_CONDITION,
//						    TestcasetoolPackage.Literals.CONDITION__EXPRESSION
//						  )
//						);
//				IObservableValue obsPreCondition = preCondProp.observe(eObject);
//				
//				
//				
//				ISWTObservableValue txtPreCondObs = SWTObservables.observeText(
//						txtPreConditions, SWT.FocusOut);
//				
//				bindingContext.bindValue(txtPreCondObs, obsPreCondition,
//						new EMFUpdateValueStrategy(EMFUpdateValueStrategy.POLICY_NEVER), new EMFUpdateValueStrategy(EMFUpdateValueStrategy.POLICY_UPDATE));

//				txtPreCondObs
//				.addValueChangeListener(new IValueChangeListener() {
//
//					@Override
//					public void handleValueChange(ValueChangeEvent event) {
//						UseCase useCase = (UseCase) eObject;
//						String value = (String) event
//								.getObservableValue().getValue();
//
//						Condition cond = useCase.getPreCondition();
//						if (cond == null){
//							cond = TestcasetoolFactory.eINSTANCE.createCondition();
//						}
//						cond.setExpression(value);
//						Command cmd = SetCommand
//								.create(editingDomain,
//										eObject,
//										TestcasetoolPackage.Literals.USE_CASE__PRE_CONDITION,
//										cond);
//						if (cmd.canExecute()){
//							editingDomain.getCommandStack().execute(cmd);
//						}
//						
//					}
//				});
				
				
//				IEMFEditValueProperty postCondProp = EMFEditProperties.value(
//						  editingDomain,
//						  FeaturePath.fromList(
//								  TestcasetoolPackage.Literals.USE_CASE__POS_CONDITION,
//						    TestcasetoolPackage.Literals.CONDITION__EXPRESSION
//						  )
//						);
//				
//				IObservableValue obsPostCondition = postCondProp.observe(eObject);
				
				IObservableValue obsPostCondition = EMFEditObservables
						.observeValue(editingDomain, eObject,
								TestcasetoolPackage.Literals.USE_CASE__POST_CONDITION);

				
				bindingContext.bindValue( SWTObservables.observeText(
						txtPostConditions, SWT.FocusOut), obsPostCondition);
				
				
				
//				IEMFEditValueProperty postCondProp = EMFEditProperties.value(
//						  editingDomain,
//						  FeaturePath.fromList(
//								  TestcasetoolPackage.Literals.USE_CASE__POS_CONDITION,
//						    TestcasetoolPackage.Literals.CONDITION__EXPRESSION
//						  )
//						);
//				
//				IObservableValue obsPostCondition = postCondProp.observe(eObject);
//				ISWTObservableValue txtPostCondObs = SWTObservables.observeText(
//						txtPostConditions, SWT.FocusOut);
//				
//				bindingContext.bindValue(txtPostCondObs, obsPostCondition,
//						new EMFUpdateValueStrategy(EMFUpdateValueStrategy.POLICY_NEVER), new EMFUpdateValueStrategy(EMFUpdateValueStrategy.POLICY_UPDATE));
//				
//				txtPostCondObs
//						.addValueChangeListener(new IValueChangeListener() {
//
//							@Override
//							public void handleValueChange(ValueChangeEvent event) {
//								UseCase useCase = (UseCase) eObject;
//								String value = (String) event
//										.getObservableValue().getValue();
//
//								Condition cond = useCase.getPosCondition();
//								if (cond == null){
//									cond = TestcasetoolFactory.eINSTANCE.createCondition();
//								}
//								cond.setExpression(value);
//								Command cmd = SetCommand
//										.create(editingDomain,
//												eObject,
//												TestcasetoolPackage.Literals.USE_CASE__POS_CONDITION,
//												cond);
//								if (cmd.canExecute()){
//									editingDomain.getCommandStack().execute(cmd);
//								}
//
//							}
//						});
//				
				
				obsManager.addObservable(obsNameFeature);
				obsManager.addObservable(obsDescFeature);
				obsManager.addObservable(obsPreCondition);
				obsManager.addObservable(obsPostCondition);
				
			}
		}
	}

	
	private void refreshActors(){
		ItemProvider listRoot = new ItemProvider("Actors",
				TestcasetoolEditPlugin.INSTANCE.getImage("full/obj16/Actor"),
				((UseCase)eObject).getParticipantActor());
		listViewer.setInput(listRoot);
	}

	
	private void createActorsSection(final Composite parent) {
		Section sectionActors = toolkit.createSection(parent,
				ExpandableComposite.EXPANDED | ExpandableComposite.TITLE_BAR);
		sectionActors.setText("Use case actors");
		sectionActors.setLayoutData(new GridData(GridData.FILL_BOTH));
		sectionActors.setLayout(FormLayoutFactory.createDetailsGridLayout(false, 1));
		
		Composite compositeActors = toolkit.createComposite(sectionActors, SWT.NONE);
		sectionActors.setClient(compositeActors);
		compositeActors.setLayout(new GridLayout(2, false));
		new Label(compositeActors, SWT.NONE);
		
		
		
		Button b = toolkit.createButton(compositeActors, "", SWT.PUSH);
		Object o = TestcasetoolEditorPlugin.getPlugin().getImage("ElementEditor.gif");
		Image image = ExtendedImageRegistry.INSTANCE.getImage(o);
		b.setImage(image);
		b.setLayoutData(new GridData(SWT.RIGHT, SWT.BOTTOM, false, false, 1, 1));
		b.addSelectionListener(new SelectionListener() {
			
			@Override
			public void widgetSelected(SelectionEvent e) {
				UseCase useCase = (UseCase)eObject;
				UseCaseModel model = (UseCaseModel)afid.getParent(afid.getParent(useCase));
				
				final ILabelProvider labelProvider = new LabelProvider()
			      {
			        @Override
			        public String getText(Object object)
			        {
			          if (object instanceof UseCase){
			        	  return ((UseCase)object).getName();
			          }
			          else if(object instanceof Actor){
			        	  return ((Actor)object).getName();
			          }
			          return "";
			        }
			        @Override
			        public Image getImage(Object object)
			        {
			        	//return null;
			          return ExtendedImageRegistry.getInstance().getImage(TestcasetoolEditorPlugin.getPlugin().getImage("Actor.gif"));
			        }
			      };
			      IItemPropertyDescriptor desc = afid.getPropertyDescriptor(eObject,
							TestcasetoolPackage.Literals.USE_CASE__PARTICIPANT_ACTOR);
			      EStructuralFeature feature = (EStructuralFeature)desc.getFeature(eObject);
			      
			      if (model.getActor().isEmpty() ){
			    	  MessageDialog.openInformation(parent.getShell(), "PluginTest", "Ther are no actors in the system");
			      }
			      else {
			    	FeatureEditorDialog dialog = new FeatureEditorDialog(parent.getShell(), labelProvider,eObject, feature.getEType(),useCase.getParticipantActor(), "Actor", model.getActor(), false,true,true);
			    	dialog.open();
					EList<Actor> result = (EList<Actor>) dialog.getResult();
					if (result != null) {
						desc.setPropertyValue(eObject, result);
						refreshActors();
					}
			      }
				
				
				
			}

			@Override
			public void widgetDefaultSelected(SelectionEvent e) {
			}
			
		});
	
		
		
		Label lblActorsInvolved = toolkit.createLabel(compositeActors, "Actors", SWT.NONE);
		lblActorsInvolved.setToolTipText("Participant actors");
		listViewer = new ListViewer(compositeActors, SWT.BORDER | SWT.V_SCROLL);
		List list = listViewer.getList();
		GridData gd_list = new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1);
		gd_list.heightHint = 80;
		list.setLayoutData(gd_list);
		listViewer.setContentProvider(new AdapterFactoryContentProvider(adapterFactory));
		listViewer.setLabelProvider(new AdapterFactoryLabelProvider(adapterFactory){
					
					@Override
					public String getText(Object object) {
						return ((Actor)object).getName();
					}
					
					@Override
					public Image getImage(Object object) {
						  return ExtendedImageRegistry.getInstance().getImage(TestcasetoolEditorPlugin.getPlugin().getImage("32px-Crystal_Clear_app_kword.png"));
					}
					
				});

	}
	
	
	@Override
	public void dispose() {
		super.dispose();
		obsManager.dispose();
	}
}